package copyengine.ai.pathFinder
{
	import copyengine.ai.pathFinder.astart.CEAStartPathFinder;
	import copyengine.ai.pathFinder.astart.IAStartBlockNodeManger;
	import copyengine.ai.pathFinder.astart.INodeHeuristicCostCalculator;
	import copyengine.ai.pathFinder.astart.parentTile.CEAStartSearchParentNode;
	import copyengine.utils.tick.GlobalTick;

	import flash.utils.Dictionary;

	public class CEPathFinderManger
	{
		private var allPathFinderNodeVector:Vector.<CEPathFinderRequestWarp>;

		private var aStartPathFinder:CEAStartPathFinder;

		private var currentPathFinderNode:CEPathFinderRequestWarp;

		private var isSearchInNextTick:Boolean = false;

		public function CEPathFinderManger()
		{
		}


		protected final function initializePathFinderCore(_heuristicCalculator:INodeHeuristicCostCalculator,
														  _blockNodeManger:IAStartBlockNodeManger = null):void
		{
			allPathFinderNodeVector = new Vector.<CEPathFinderRequestWarp>();
			aStartPathFinder = new CEAStartPathFinder();
			aStartPathFinder.initialize(_heuristicCalculator, _blockNodeManger);
		}

		public final function dispose():void
		{
			GlobalTick.instance.removeTickNodeByFunction(tickSearch);
			aStartPathFinder.dispose();
			allPathFinderNodeVector.length = 0;
			allPathFinderNodeVector = null;
			aStartPathFinder = null;
		}

		protected function doDispose():void
		{
		}

		/**
		 * 设置搜索的Dic,当地图数据发生改变后重新设置
		 */
		protected final function setAStartNodeDic(_aStartNodeDic:Dictionary):void
		{
			aStartPathFinder.setAStartNodeDic(_aStartNodeDic);
		}

		public final function search(_fromTileIndexX:int, _fromTileIndexY:int, _toTileIndexX:int, _toTileIndexY:int, _callBackFunction:Function):void
		{
			var findNode:CEPathFinderRequestWarp = new CEPathFinderRequestWarp();
			findNode.fromTileIndexX = _fromTileIndexX;
			findNode.fromTileIndexY = _fromTileIndexY;
			findNode.toTileIndexX = _toTileIndexX;
			findNode.toTileIndexY = _toTileIndexY;
			findNode.callBackFunction = _callBackFunction;
			findNode.searchTime = 0;

			allPathFinderNodeVector.push(findNode);

			//如果当前没有节点正在Search则开始搜索新的节点
			if (currentPathFinderNode == null)
			{
				currentPathFinderNode = allPathFinderNodeVector.pop();
				resetAStartPathFinder(currentPathFinderNode);
			}
			tryToSearchInNextTick();
		}

		public final function removeSearchByCallBackFunction(_callBackFunction:Function):void
		{
			if (currentPathFinderNode && currentPathFinderNode.callBackFunction == _callBackFunction)
			{
				currentPathFinderNode.callBackFunction = null;
			}
			for (var i:int = 0; i < allPathFinderNodeVector.length; i++)
			{
				if (_callBackFunction == allPathFinderNodeVector[i].callBackFunction)
				{
					allPathFinderNodeVector.splice(i, 1);
					break;
				}
			}
		}

		private function tickSearch():void
		{
			isSearchInNextTick = false;
			for (var i:int = 0; i < CEPathFinderConfig.EACH_TICK_SEARCH_COUNT; i++)
			{
				if (currentPathFinderNode)
				{
					doSearch();
				}
				else
				{
					break;
				}
			}
			tryToSearchInNextTick();
		}

		private function doSearch():void
		{
			var result:int = aStartPathFinder.tickSearch();
			if (result == CEPathFinderConfig.SEARCH_RESULT_NOT_FINISHED)
			{
				currentPathFinderNode.searchTime++;
				if (currentPathFinderNode.searchTime >= CEPathFinderConfig.MAX_SEARCH_STEP)
				{
					//currentPathFinderNode.callBackFunction 有可能在调用中途会
					//调用removeSearchByCallBackFunction 导致callBackFunction被制空
					currentPathFinderNode.callBackFunction && currentPathFinderNode.callBackFunction(CEPathFinderConfig.SEARCH_RESULT_FAILED, null);
					tryToInitNextFinderNode();
					return;
				}
			}
			else if (result == CEPathFinderConfig.SEARCH_RESULT_FAILED)
			{
				currentPathFinderNode.callBackFunction && currentPathFinderNode.callBackFunction(CEPathFinderConfig.SEARCH_RESULT_FAILED, null);
				tryToInitNextFinderNode();
				return;
			}
			else
			{
				var resultPackageVector:Vector.<CEPathFinderResultPackage> = generateAStartPathFindResultPackage(aStartPathFinder.getPathEndNode());
				currentPathFinderNode.callBackFunction && currentPathFinderNode.callBackFunction(CEPathFinderConfig.SEARCH_RESULT_SUCCEED,
																								 resultPackageVector);
				tryToInitNextFinderNode();
				return;
			}
		}

		private function generateAStartPathFindResultPackage(_targetNode:CEAStartSearchParentNode):Vector.<CEPathFinderResultPackage>
		{
			var currentNode:CEAStartSearchParentNode = _targetNode;
			var resultPackageVector:Vector.<CEPathFinderResultPackage> = new Vector.<CEPathFinderResultPackage>();

			while (currentNode.parentNode != null)
			{
				var resultPackage:CEPathFinderResultPackage = new CEPathFinderResultPackage();
				resultPackage.tileIndexX = currentNode.tileIndexX;
				resultPackage.tileIndexY = currentNode.tileIndexY;
				resultPackageVector.push(resultPackage);

				currentNode = currentNode.parentNode;
			}
			return resultPackageVector;
		}


		private function tryToInitNextFinderNode():void
		{
			currentPathFinderNode = allPathFinderNodeVector.pop();
			if (currentPathFinderNode)
			{
				resetAStartPathFinder(currentPathFinderNode);
			}
		}

		/**
		 *在下一帧开始搜索,如果下帧已确定搜索则直接返回
		 */
		private function tryToSearchInNextTick():void
		{
			if (!isSearchInNextTick && currentPathFinderNode)
			{
				isSearchInNextTick = true;
				GlobalTick.instance.callLaterAfterTickCount(tickSearch);
			}
		}

		/**
		 *重置A*搜索
		 */
		private function resetAStartPathFinder(_pathFinderNode:CEPathFinderRequestWarp):void
		{
			if (_pathFinderNode)
			{
				aStartPathFinder.resetSearchParameter(_pathFinderNode.fromTileIndexX,
													  _pathFinderNode.fromTileIndexY,
													  _pathFinderNode.toTileIndexX,
													  _pathFinderNode.toTileIndexY);
			}
		}
	}
}
